import axios from 'axios';
import authApi from '@/api/auth';
import { isTokenExpired, getToken } from './authUtils';

// 创建axios实例
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL + '/api' || '/api', // 使用环境变量或默认值
  timeout: 10000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
});

// 是否正在刷新token的标志
let isRefreshing = false;
let failedQueue = [];

// 处理失败的请求队列
const processQueue = (error, token = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });
  
  failedQueue = [];
};

// 请求拦截器
request.interceptors.request.use(
  async config => {
    // 在请求发送之前做一些处理
    let token = getToken();
    
    if (token) {
      // 检查token是否即将过期（提前5分钟）
      const decoded = JSON.parse(atob(token.split('.')[1]));
      const currentTime = Math.floor(Date.now() / 1000);
      const timeUntilExpiry = decoded.exp - currentTime;
      
      // 如果token将在5分钟内过期，则刷新token
      if (timeUntilExpiry < 300 && !config.url.includes('/auth/refresh')) {
        if (!isRefreshing) {
          isRefreshing = true;
          
          try {
            const refreshResponse = await authApi.refreshToken(token);
            if (refreshResponse.code === 200) {
              const newToken = refreshResponse.data.token;
              localStorage.setItem('adminToken', newToken);
              processQueue(null, newToken);
              config.headers.Authorization = `Bearer ${newToken}`;
            }
          } catch (error) {
            processQueue(error, null);
            localStorage.removeItem('adminToken');
            window.location.href = '/login';
          } finally {
            isRefreshing = false;
          }
        } else {
          // 如果正在刷新token，将请求加入队列
          return new Promise((resolve, reject) => {
            failedQueue.push({ resolve, reject });
          }).then(token => {
            config.headers.Authorization = `Bearer ${token}`;
            return config;
          }).catch(err => {
            return Promise.reject(err);
          });
        }
      } else {
        // 设置token到请求头
        config.headers.Authorization = `Bearer ${token}`;
      }
    }
    
    return config;
  },
  error => {
    // 处理请求错误
    console.error('请求配置错误:', error);
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  response => {
    // 对响应数据做处理
    const res = response.data;
    
    // 根据自定义状态码处理响应
    if (res.code !== 200) {
      // 处理业务错误
      console.error('业务错误:', res.message);
      
      // 特殊状态码处理
      if (res.code === 401) {
        // 未授权，跳转到登录页面
        localStorage.removeItem('adminToken');
        window.location.href = '/login';
      }
      
      return Promise.reject(new Error(res.message || '请求失败'));
    }
    
    return res;
  },
  error => {
    // 处理响应错误
    console.error('响应错误:', error);
    
    // 网络错误处理
    if (!error.response) {
      console.error('网络错误，请检查网络连接');
      return Promise.reject(new Error('网络错误，请检查网络连接'));
    }
    
    // HTTP状态码处理
    const status = error.response.status;
    let errorMessage = '请求失败';
    
    switch (status) {
      case 400:
        errorMessage = '请求参数错误';
        break;
      case 401:
        errorMessage = '未授权，请重新登录';
        localStorage.removeItem('adminToken');
        window.location.href = '/login';
        break;
      case 403:
        errorMessage = '权限不足';
        break;
      case 404:
        errorMessage = '资源不存在';
        break;
      case 409:
        errorMessage = '资源冲突';
        break;
      case 422:
        errorMessage = '业务逻辑错误';
        break;
      case 429:
        errorMessage = '请求过于频繁';
        break;
      case 500:
        errorMessage = '服务器内部错误';
        break;
      case 503:
        errorMessage = '服务不可用';
        break;
      default:
        errorMessage = error.response.data?.message || '请求失败';
    }
    
    console.error(`HTTP错误 ${status}: ${errorMessage}`);
    return Promise.reject(new Error(errorMessage));
  }
);

export default request;
